/* Copyright (c) 2008 LepomisLab.com, Andrey Turkin
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "NSIBObjectData.h"
#include "NSKeyedUnarchiver.h"
#include "NSNibConnector.h"
#include "NSWindowTemplate.h"

using namespace std;

IMPLEMENT_DYNAMIC_CLASS(NSIBObjectData, NSObject)

 obj_map *build_map(wxObject *keys, wxObject *values)
 {
	 NSArray *_keys = wxDynamicCast(keys, NSArray);
	 NSArray *_vals = wxDynamicCast(values, NSArray);
	 wxASSERT(_keys && _vals);
	 obj_map *map = new obj_map();
	 for(size_t i=0;i<_keys->length();i++)
		 map->insert(obj_map::value_type(_keys->getObject(i), _vals->getObject(i)));
	 return map;
 }

void NSIBObjectData::initWithUnarchiver(NSKeyedUnarchiver *archiver)
{
	_root = wxDynamicCast(archiver->decodeObjectForKey(wxT("NSRoot")), NSCustomObject);
	wxASSERT(_root);
	wxObject *o = archiver->decodeObjectForKey(wxT("NSVisibleWindows"));
	if (o)
	{
		_visibleWindows = wxDynamicCast(o, NSMutableSet);
		wxASSERT(_visibleWindows);
	} else
		_visibleWindows = new NSMutableSet();

	archiver->decodeObjectForKey(wxT("NSAccessibilityConnectors"));
	archiver->decodeObjectForKey(wxT("NSFontManager"));
	archiver->decodeObjectForKey(wxT("NSFramework"));
	archiver->decodeIntForKey(wxT("NSNextOid"));

	_objects = build_map(archiver->decodeObjectForKey(wxT("NSObjectsKeys")),
						 archiver->decodeObjectForKey(wxT("NSObjectsValues")));
	_names = build_map(archiver->decodeObjectForKey(wxT("NSNamesKeys")),
					   archiver->decodeObjectForKey(wxT("NSNamesValues")));
	_oids = build_map(archiver->decodeObjectForKey(wxT("NSOidsKeys")),
						archiver->decodeObjectForKey(wxT("NSOidsValues")));
	_classes = build_map(archiver->decodeObjectForKey(wxT("NSClassesKeys")),
						archiver->decodeObjectForKey(wxT("NSClassesValues")));

	o = archiver->decodeObjectForKey(wxT("NSConnections"));
	if (o)
	{
		_connections = wxDynamicCast(o, NSMutableArray);
		wxASSERT(_connections);
	}
	else
		_connections = NULL;
}

void NSIBObjectData::instantiateWithOwner(NSObject* owner, NSKeyedUnarchiver* archiver)
{
	_root->SetObject(owner);
	if (_connections) 
		for(size_t i = 0; i < _connections->length(); i++)
		{
			NSNibConnector* c = wxDynamicCast(_connections->getObject(i), NSNibConnector);
			if (c)
			{
				c->instantiateWithInstantiator(this, archiver);
				c->establishConnection();
			}
		}

	for(obj_map::iterator i = _names->begin();i!=_names->end();i++)
	{
		NSObject *obj = wxDynamicCast(i->first, NSObject);
		wxASSERT(obj);
		NSWindowTemplate* wnd = wxDynamicCast(obj, NSWindowTemplate);
		if (wnd)
		{
			if (!wnd->realObject())
			{
				obj = instantiateObject(wnd, archiver);
				// tlo->add(obj);
			}
		} else {
			if (!i->second || i->second == owner)
			{
				//tlo->add(obj);
			}
		}
		obj->awakeFromNib();
	}

	NSEnumerator *i = _visibleWindows->enumerator();
	wxObject *o;
	while((o=i->NextObject())!=NULL)
	{
		NSWindow *w = wxDynamicCast(o, NSWindow);
		wxASSERT(w);
		w->orderFront();
	}
	delete i;
}

NSObject* NSIBObjectData::instantiateObject(NSObject *source, NSKeyedUnarchiver* archiver)
{
	return source->nibInstantiate(archiver);
}
